package orders

import (
	rich_err "app/error"
	"app/models"
	"app/service"
	"app/utils"
	"errors"
	"math"
	"strconv"

	"github.com/jinzhu/gorm"

	mapset "github.com/deckarep/golang-set/v2"

	"github.com/gin-gonic/gin"
)

func Gets(context *gin.Context) ([]*models.OrdersDetail, *models.Pager, *rich_err.RichError) {
	base := models.Orm.Model(&models.Orders{}).
		Select("orders.*,  seed_variant.name as seed_variant_name, seed_category.name as seed_category_name").
		Joins("LEFT JOIN seed_variant ON orders.seed_variant_id = seed_variant.id").
		Joins("LEFT JOIN seed_category ON seed_variant.category_id = seed_category.id")
	if status, ok := context.GetQueryArray("filter_status"); ok {
		filterStatus := make([]int, 0)
		for _, s := range status {
			statusInt, _ := strconv.Atoi(s)
			filterStatus = append(filterStatus, statusInt)
		}
		base = base.Where("`order_status` in (?) ", filterStatus)
	}
	if greenhouseID, ok := context.GetQuery("greenhouse_id"); ok {
		var ordersID []int
		err := models.Orm.Table("greenhouse_allocation_record").
			Select("order_id").
			Where("greenhouse_id = ?", greenhouseID).
			Pluck("order_id", &ordersID).Error
		if err != nil {
			return nil, nil, rich_err.NewError(rich_err.RequestInvalid, err)
		}
		if len(ordersID) == 0 {
			return []*models.OrdersDetail{}, &models.Pager{Count: 0, Index: 1, Size: 0}, nil
		}
		base = base.Where("orders.id in (?) ", ordersID)
	}
	//user, _ := engine.User(context)
	//if user.CheckRole("SowingManager") {
	//	// 播种管理员
	//	// 订单状态只显示 2-待播种, 3-已播种, 4-待分棚, 5-已分棚
	//	base = base.Where("`order_status` in (?) ", []int{2, 3, 4, 5})
	//}
	//
	//if user.CheckRole("GreenhouseManager") {
	//	// 大棚管理员
	//	// 订单状态只显示  5-已分棚 , 6-待分苗床, 7-已分苗床, 8-待出苗, 9-已出苗
	//	base = base.Where("`order_status` in (?) ", []int{5, 6, 7, 8, 9})
	//}

	results, pager, err := service.GetDetails[models.OrdersDetail](context, base, models.Orders{}.TableName(), map[string]string{"seed_variant_name": "seed_variant.name", "seed_category_name": "seed_category.name"})

	if err != nil {
		return nil, nil, rich_err.NewError(rich_err.RequestInvalid, err)
	}
	return results, pager, nil
}

func AlertList(context *gin.Context, alertType string) ([]*models.OrdersDetail, *models.Pager, *rich_err.RichError) {
	// 根据alert_type 确定要筛选的orders id 的范围
	var ids, sowingIDs, sowedIDs, paymentIDs []int
	var err error
	// 订单状态是待播种,或者有预计播种日期,但是无实际播种日期
	err = models.Orm.Table("orders").
		Select("id").
		Where("order_status = ? OR (estimated_sowing_date <> '' AND actual_sowing_date = '')", 2).
		Pluck("id", &sowingIDs).Error

	if err != nil {
		return nil, nil, rich_err.NewError(rich_err.RequestInvalid, err)
	}
	// 订单状态是待出苗,或者有预计出苗日期,但是无实际出苗日期
	err = models.Orm.Table("orders").
		Select("id").
		Where("order_status = ? OR (estimated_seedling_date <> '' AND actual_seedling_date = '')", 8).
		Pluck("id", &sowedIDs).Error

	if err != nil {
		return nil, nil, rich_err.NewError(rich_err.RequestInvalid, err)
	}
	// 订单状态已出苗和待收款
	err = models.Orm.Table("orders o").
		Select("o.id").
		Joins("LEFT JOIN (SELECT order_id, SUM(amount) AS total_payment FROM payment_record GROUP BY order_id) p ON o.id = p.order_id").
		Where("o.order_status in (?)", []int{9, 10}).
		Pluck("id", &paymentIDs).Error

	if err != nil {
		return nil, nil, rich_err.NewError(rich_err.RequestInvalid, err)
	}

	switch alertType {
	case "sowing":
		// 全部播种提醒列表
		ids = sowingIDs
	case "sowed":
		// 已加入播种提醒列表的,不需要加入出苗提醒
		ids = mapset.NewSet(sowedIDs...).Difference(mapset.NewSet(sowingIDs...)).ToSlice()
	case "payment":
		// 已加入播种提醒,出苗提醒的订单,不需要加入支付提醒
		ids = mapset.NewSet(paymentIDs...).Difference(mapset.NewSet(sowingIDs...).Union(mapset.NewSet(sowedIDs...))).ToSlice()
	}

	if len(ids) == 0 {
		return []*models.OrdersDetail{}, &models.Pager{Count: 0, Index: 1, Size: 0}, nil
	}

	if greenhouseID, ok := context.GetQuery("greenhouse_id"); ok {
		var ordersID []int
		err := models.Orm.Table("greenhouse_allocation_record").
			Select("order_id").
			Where("greenhouse_id = ?", greenhouseID).
			Pluck("order_id", &ordersID).Error
		if err != nil {
			return nil, nil, rich_err.NewError(rich_err.RequestInvalid, err)
		}
		if len(ordersID) == 0 {
			return []*models.OrdersDetail{}, &models.Pager{Count: 0, Index: 1, Size: 0}, nil
		}
		ids = mapset.NewSet(ids...).Intersect(mapset.NewSet(ordersID...)).ToSlice()
	}

	base := models.Orm.Model(&models.Orders{}).
		Select("orders.*,  seed_variant.name as seed_variant_name, seed_category.name as seed_category_name").
		Joins("LEFT JOIN seed_variant ON orders.seed_variant_id = seed_variant.id").
		Joins("LEFT JOIN seed_category ON seed_variant.category_id = seed_category.id").Where("orders.id in (?) ", ids)
	if status, ok := context.GetQueryArray("filter_status"); ok {
		filterStatus := make([]int, 0)
		for _, s := range status {
			statusInt, _ := strconv.Atoi(s)
			filterStatus = append(filterStatus, statusInt)
		}
		base = base.Where("`order_status` in (?) ", filterStatus)
	}
	//user, _ := engine.User(context)
	//if user.CheckRole("SowingManager") {
	//	// 播种管理员
	//	// 订单状态只显示 2-待播种, 3-已播种, 4-待分棚, 5-已分棚
	//	base = base.Where("`order_status` in (?) ", []int{2, 3, 4, 5})
	//}
	//
	//if user.CheckRole("GreenhouseManager") {
	//	// 大棚管理员
	//	// 订单状态只显示  5-已分棚 , 6-待分苗床, 7-已分苗床, 8-待出苗, 9-已出苗
	//	base = base.Where("`order_status` in (?) ", []int{5, 6, 7, 8, 9})
	//}

	results, pager, err := service.GetDetails[models.OrdersDetail](context, base, models.Orders{}.TableName(), map[string]string{"seed_variant_name": "seed_variant.name", "seed_category_name": "seed_category.name"})

	if err != nil {
		return nil, nil, rich_err.NewError(rich_err.RequestInvalid, err)
	}
	return results, pager, nil
}

func Get(id string) (*models.OrdersDetail, *rich_err.RichError) {
	base := models.Orm.Model(&models.Orders{}).
		Select("orders.*,  seed_variant.name as seed_variant_name, seed_category.name as seed_category_name").
		Joins("LEFT JOIN seed_variant ON orders.seed_variant_id = seed_variant.id").
		Joins("LEFT JOIN seed_category ON seed_variant.category_id = seed_category.id")

	result, err := service.GetDetail[models.OrdersDetail](id, base)

	if err != nil {
		return nil, rich_err.NewError(rich_err.RequestInvalid, err)
	}
	return result, nil
}

func Create(context *gin.Context) (*models.OrdersDetail, *rich_err.RichError) {
	req := new(models.OrdersCore)
	if err := context.ShouldBindJSON(req); err != nil {
		return nil, rich_err.NewError(rich_err.RequestInvalid, err)
	}
	data := models.Orders{OrdersCore: *req}
	if data.Name == "" {
		// 获取客户ID和种子型号ID
		seedVariantId := data.SeedVariantID

		// 查询种子型号名称
		seedVariantName := getVariantNameById(strconv.Itoa(seedVariantId))
		// 拼接订单名称
		orderName := data.Customer + "-" + seedVariantName
		data.Name = orderName
	}
	// 计算种子数量
	if data.SeedQuantity == 0 {
		data.SeedQuantity = data.TrayNumber * data.UnitNumber
	}
	// 订单要求的提苗数量
	if data.RequiredSeedlingQuantity == 0 {
		data.RequiredSeedlingQuantity = data.RequiredSeedlingTray * data.RequiredSeedlingUnit
	}
	if data.OrderStatus == 0 {
		data.OrderStatus = 2
	}
	result := models.Orm.Create(&data)
	if result.Error != nil {
		return nil, rich_err.NewError(rich_err.DatabaseFailed, result.Error)
	}
	return Get(strconv.Itoa(data.ID))
}

func Update(context *gin.Context) (*models.OrdersDetail, *rich_err.RichError) {
	req := new(models.OrdersDelta)
	if err := context.ShouldBindJSON(req); err != nil {
		return nil, rich_err.NewError(rich_err.RequestInvalid, err)
	}

	data, err := service.Get[models.Orders](context)
	if err != nil {
		return nil, rich_err.NewError(rich_err.RequestInvalid, err)
	}
	if req.Customer != nil {
		data.Customer = req.Customer.(string)
	}
	if req.Name != nil {
		data.Name = req.Name.(string)
	}
	if req.Phone != nil {
		data.Phone = req.Phone.(string)
	}
	if req.SeedVariantID != nil {
		data.SeedVariantID = int(math.Round(req.SeedVariantID.(float64)))
	}
	if req.TrayNumber != nil {
		data.TrayNumber = int(math.Round(req.TrayNumber.(float64)))
	}
	if req.UnitNumber != nil {
		data.UnitNumber = int(math.Round(req.UnitNumber.(float64)))
	}
	//计算数量改用盘总数*每盘数量
	if req.SeedQuantity != nil {
		data.SeedQuantity = int(math.Round(req.SeedQuantity.(float64)))
	} else {
		data.SeedQuantity = data.TrayNumber * data.UnitNumber
	}
	if req.RequiredSeedlingTray != nil {
		data.RequiredSeedlingTray = int(math.Round(req.RequiredSeedlingTray.(float64)))
	}
	if req.RequiredSeedlingUnit != nil {
		data.RequiredSeedlingUnit = int(math.Round(req.RequiredSeedlingUnit.(float64)))
	}
	// 订单要求的提苗数量
	if req.RequiredSeedlingQuantity != nil {
		data.RequiredSeedlingQuantity = int(math.Round(req.RequiredSeedlingQuantity.(float64)))
	} else {
		data.RequiredSeedlingQuantity = data.RequiredSeedlingTray * data.RequiredSeedlingUnit
	}
	if req.Care != nil {
		data.Care = req.Care.(bool)
	}
	if req.SeedRemark != nil {
		data.SeedRemark = req.SeedRemark.(string)
	}
	if req.Remark != nil {
		data.Remark = req.Remark.(string)
	}
	if req.EstimatedSowingDate != nil {
		data.EstimatedSowingDate = utils.ToDateV2(req.EstimatedSowingDate.(string))
	}
	if req.ActualSowingDate != nil {
		data.ActualSowingDate = utils.ToDateV2(req.ActualSowingDate.(string))
	}
	if req.EstimatedSeedlingDate != nil {
		data.EstimatedSeedlingDate = utils.ToDateV2(req.EstimatedSeedlingDate.(string))
	}
	if req.ActualSeedlingDate != nil {
		data.ActualSeedlingDate = utils.ToDateV2(req.ActualSeedlingDate.(string))
	}
	if req.SowedQuantity != nil {
		data.SowedQuantity = int(math.Round(req.SowedQuantity.(float64)))
	}
	if req.AllocatedSeedbedQuantity != nil {
		data.AllocatedSeedbedQuantity = int(math.Round(req.AllocatedSeedbedQuantity.(float64)))
	}

	if req.DeliveredQuantity != nil {
		data.DeliveredQuantity = int(math.Round(req.DeliveredQuantity.(float64)))
	}
	if req.TotalAmount != nil {
		data.TotalAmount = req.TotalAmount.(float64)
	}
	if req.ReceivedAmount != nil {
		data.ReceivedAmount = req.ReceivedAmount.(float64)
	}
	if req.PaymentStatus != nil {
		data.PaymentStatus = int(math.Round(req.PaymentStatus.(float64)))
	}
	if req.OrderStatus != nil {
		data.OrderStatus = int(math.Round(req.OrderStatus.(float64)))
	}

	result := models.Orm.Save(data)
	if result.Error != nil {
		return nil, rich_err.NewError(rich_err.DatabaseFailed, result.Error)
	}
	return Get(strconv.Itoa(data.ID))
}

func Delete(context *gin.Context) *rich_err.RichError {
	data, err := service.Get[models.Orders](context)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil
		}
		return rich_err.NewError(rich_err.RequestInvalid, err)
	}
	result := models.Orm.Delete(data)
	if result.Error != nil {
		return rich_err.NewError(rich_err.DatabaseFailed, result.Error)
	}
	// 联动删除其他项
	conditions := map[string]interface{}{"order_id = ?": data.ID}
	richErr := service.DeleteByConditions[models.GreenhouseAllocationRecord](conditions)
	if richErr != nil {
		return richErr
	}
	richErr = service.DeleteByConditions[models.MedicationRecord](conditions)
	if richErr != nil {
		return richErr
	}
	richErr = service.DeleteByConditions[models.SeedlingRecord](conditions)
	if richErr != nil {
		return richErr
	}
	richErr = service.DeleteByConditions[models.SowingRecord](conditions)
	if richErr != nil {
		return richErr
	}
	richErr = service.DeleteByConditions[models.PaymentRecord](conditions)
	if richErr != nil {
		return richErr
	}

	richErr = service.DeleteByConditions[models.SeedbedAllocationRecord](conditions)
	if richErr != nil {
		return richErr
	}

	richErr = service.DeleteByConditions[models.SeedbedAllocationBatchRecord](conditions)
	if richErr != nil {
		return richErr
	}

	richErr = service.DeleteByConditions[models.TaskRecord](conditions)
	if richErr != nil {
		return richErr
	}

	return nil
}

func getVariantNameById(id string) string {
	type Variant struct {
		ID           string
		VariantName  string
		CategoryName string
	}
	var variant Variant
	err := models.Orm.Table("seed_variant").Select("seed_variant.name as variant_name, seed_category.name as category_name").
		Joins("left join seed_category on seed_variant.category_id = seed_category.id").
		Where("seed_variant.id = ?", id).
		Scan(&variant).Error
	if err != nil {
		return ""
	}
	return variant.CategoryName + "-" + variant.VariantName
}

func UpdateSowedQuantity(orderID int) error {
	var sowedQuantity int
	if err := models.Orm.Model(&models.SowingRecord{}).Where("order_id = ?", orderID).Select("COALESCE(sum(quantity), 0)").Row().Scan(&sowedQuantity); err != nil {
		return err
	}

	if err := models.Orm.Model(&models.Orders{}).Where("id = ?", orderID).Update("sowed_quantity", sowedQuantity).Error; err != nil {
		return err
	}

	return nil
}

func UpdateAllocatedSeedbedQuantity(orderID int) error {
	var allocatedSeedbedQuantity int
	if err := models.Orm.Model(&models.SeedbedAllocationBatchRecord{}).Where("order_id = ?", orderID).Select("COALESCE(sum(quantity), 0)").Row().Scan(&allocatedSeedbedQuantity); err != nil {
		return err
	}

	if err := models.Orm.Model(&models.Orders{}).Where("id = ?", orderID).Update("allocated_seedbed_quantity", allocatedSeedbedQuantity).Error; err != nil {
		return err
	}

	return nil
}

func UpdateDeliveredQuantity(orderID int) error {
	var deliveredQuantity int
	if err := models.Orm.Model(&models.SeedlingRecord{}).Where("order_id = ?", orderID).Select("COALESCE(sum(quantity), 0)").Row().Scan(&deliveredQuantity); err != nil {
		return err
	}

	if err := models.Orm.Model(&models.Orders{}).Where("id = ?", orderID).Update("delivered_quantity", deliveredQuantity).Error; err != nil {
		return err
	}

	return nil
}

func UpdateReceivedAmount(orderID int) error {
	var receivedAmount float64
	if err := models.Orm.Model(&models.PaymentRecord{}).Where("order_id = ?", orderID).Select("COALESCE(sum(quantity), 0)").Row().Scan(&receivedAmount); err != nil {
		return err
	}
	if err := models.Orm.Model(&models.Orders{}).Where("id = ?", orderID).Update("received_amount", receivedAmount).Error; err != nil {
		return err
	}
	return nil
}
